<script lang="ts">
import {
  defineComponent,
  onMounted,
  ref,
  reactive,
  computed,
  nextTick,
} from "vue";

export default defineComponent({
  props: {
    modelValue: { type: Number, required: true },
    color: { type: String, default: "#1b9a43" },
    layerColor: { type: String, default: "#eeeeee" },
    borderColor: { type: String, default: "#eeeeee" },
  },
  emits: {
    "update:modelValue": (value: number) => typeof value === "number",
  },
  setup(props, ctx) {
    let width = 0;

    onMounted(() => {
      nextTick(() => {
        width = (elRef.value as HTMLElement).getBoundingClientRect().width;
      });
    });

    const elRef = ref();

    const drag = reactive({ run: false, value: 0 });
    const value = computed(() => (drag.run ? drag.value : props.modelValue));

    const touchData = { pageX: 0, value: 0 };
    const onTouchStart = (e: TouchEvent) => {
      const current = props.modelValue || 0;
      drag.value = current;
      drag.run = true;
      touchData.pageX = e.touches[0].pageX;
      touchData.value = current;
    };
    const onTouchMove = (e: TouchEvent) => {
      if (!drag.run) return;
      const pageX = e.touches[0].pageX;
      const value = ((pageX - touchData.pageX) / width) * 100;
      drag.value = Math.min(100, Math.max(0, touchData.value + value));
    };
    const onTouchEnd = () => {
      if (!drag.run) return;
      ctx.emit("update:modelValue", drag.value);
      nextTick(() => (drag.run = false));
    };
    return { elRef, value, onTouchStart, onTouchMove, onTouchEnd };
  },
});
</script>

<template>
  <div
    class="progress-comp"
    ref="elRef"
    :style="{ backgroundColor: layerColor }"
  >
    <div
      class="progress-comp-line"
      :style="{ width: `${value}%`, backgroundColor: color }"
    ></div>
    <div
      class="progress-comp-slider-w"
      :style="{ left: `${value}%` }"
      @touchstart="onTouchStart"
      @touchmove.capture="onTouchMove"
      @touchend="onTouchEnd"
    >
      <div
        class="progress-comp-slider"
        :style="{ backgroundColor: color, borderColor }"
      ></div>
    </div>
  </div>
</template>

<style lang="less">
.progress-comp {
  position: relative;
  height: 2px;

  .progress-comp-line {
    position: absolute;
    left: 0;
    top: 0;
    width: 0;
    height: 100%;
    border-radius: 2px;
  }

  .progress-comp-slider-w {
    position: absolute;
    top: 50%;
    transform: translate3d(-50%, -50%, 0);
  }

  .progress-comp-slider {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    border: 3px solid;
  }
}
</style>
